from typing import List, Type, Union
from sqlalchemy.orm import Session
from schemas.shipping_address import CreateShippingAddressRequest, UpdateShippingAddressRequest
from db import models
from sqlalchemy import and_
from datetime import datetime


class ShippingAddress:
    @staticmethod
    def create(db: Session, data: CreateShippingAddressRequest) -> models.ShippingAddress:
        item = models.ShippingAddress(
            created_on=data.created_on,
            created_by=data.created_by,
            customer_id=data.customer_id,
            recipient=data.recipient,
            phone=data.phone,
            province=data.province,
            city=data.city,
            district=data.district,
            details_address=data.details_address,
            is_default=data.is_default,
        )
        db.add(item)
        db.commit()
        return item

    @staticmethod
    def get(db: Session, address_id: int) -> Union[models.ShippingAddress, None]:
        return db.query(models.ShippingAddress).get(address_id)

    @staticmethod
    def count_by_customer_id(db: Session, customer_id: int) -> int:
        return db.query(models.ShippingAddress).filter_by(customer_id=customer_id, status=1).count()

    @staticmethod
    def get_all_by_customer_id(db: Session, customer_id: int) -> List[Type[models.ShippingAddress]]:
        return db.query(models.ShippingAddress).filter_by(customer_id=customer_id, status=1).all()

    @staticmethod
    def update(db: Session, data: UpdateShippingAddressRequest) -> None:
        db.query(models.ShippingAddress).filter_by(id=data.id).update({
            "updated_on": data.updated_on,
            "recipient": data.recipient,
            "phone": data.phone,
            "province": data.province,
            "city": data.city,
            "district": data.district,
            "details_address": data.details_address,
        })
        db.commit()

    @staticmethod
    def set_default_address(db: Session, customer_id: int, address_id: int) -> None:
        db.query(models.ShippingAddress).filter(
            and_(
                models.ShippingAddress.customer_id == customer_id,
                models.ShippingAddress.id != address_id,
                models.ShippingAddress.status == 1)
        ).update({
            "is_default": False,
        })

        db.query(models.ShippingAddress).filter_by(id=address_id, status=1).update({
            "is_default": True,
        })

        db.commit()

    @staticmethod
    def get_default_address(db: Session, customer_id: int) -> None:
        return db.query(models.ShippingAddress).filter_by(customer_id=customer_id, is_default=True, status=1).first()

    @staticmethod
    def delete(db: Session, customer_id: int, address_id: int) -> None:
        db.query(models.ShippingAddress).filter_by(id=address_id, customer_id=customer_id).update({
            "status": 0,
            "updated_on": datetime.now(),
        })
        db.commit()
